#include "metanet.h"

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <time.h>

#include "metanet_malloc.h"

struct logger {
    FILE *handle;
    char *filename;
    uint32_t starttime;
    int close;
};

struct logger *
logger_create(void) {
    struct logger *inst = (struct logger *)metanet_malloc(sizeof(*inst));
    inst->handle = NULL;
    inst->close = 0;
    inst->filename = NULL;
    return inst;
}

void
logger_release(struct logger *inst) {
    if (inst->close) {
        fclose(inst->handle);
    }
    metanet_free(inst->filename);
    metanet_free(inst);
}

#define SIZETIMEFMT 250
static int
timestring(struct logger *inst, char tmp[SIZETIMEFMT]) {
    uint64_t now = metanet_now();
    time_t ti = now/1000 + inst->starttime;
    struct tm info;
    (void)localtime_r(&ti, &info);
    strftime(tmp, SIZETIMEFMT, "%D %T", &info);
    return now % 1000;
}

static int
logger_cb(struct metanet_context *ctx, void *ud, int type, int session, uint32_t source, const void *msg, size_t sz) {
    struct logger *inst = ud;
    switch (type) {
    case PTYPE_SYSTEM: {
        if (inst->filename) {
            inst->handle = freopen(inst->filename, "a", inst->handle);
        }
        break;
    }
    case PTYPE_TEXT: {
        if (inst->filename) {
            char tmp[SIZETIMEFMT] = {0};
            int csec = timestring(ud, tmp);
            fprintf(inst->handle, "%s.%02d", tmp, csec);
        }
        fprintf(inst->handle, "[:%08x]", source);
        fwrite(msg, sz, 1, inst->handle);
        fprintf(inst->handle, "\n");
        fflush(inst->handle);
    }
    break;
    case PTYPE_TEST: {
        if (inst->filename) {
            char tmp[SIZETIMEFMT] = {0};
            int csec = timestring(ud, tmp);
            fprintf(inst->handle, "%s.%02d", tmp, csec);
        }
        fprintf(inst->handle, "[:%08x]", source);
        fprintf(inst->handle, "test :");
        fwrite(msg, sz, 1, inst->handle);
        fprintf(inst->handle, "\n");
        fflush(inst->handle);
    }
    break;
    }
    return 0;
}

int
logger_init(struct logger *inst, struct metanet_context *ctx, const char *parm) {
    const char *r = metanet_command(ctx, "STARTTIME", NULL);
    inst->starttime = strtoul(r, NULL, 10);
    if (parm) {
        inst->handle = fopen(parm, "a");
        if (inst->handle == NULL) {
            return 1;
        }
        inst->filename = (char*)metanet_malloc(strlen(parm)+1);
        strcpy(inst->filename, parm);
        inst->close = 1;
    } else {
        inst->handle = stdout;
    }

    if (inst->handle) {
        metanet_callback(ctx, (void*)inst, (metanet_cb)logger_cb);
        return 0;
    }
    return 1;
}